using System;
using System.Collections.Generic;

namespace AIFSCMSClient
{
    /// <summary>
    /// Fact Expression Builder will be used by Clients that just need to build their facts and check against
    /// existing rules in the repository.
    /// This should not be used by Rule building application because of it's limitted operator exposure. This class
    /// only supports equal to and is null operators.
    /// RuleExpressionBuilder should be used for rule building.
    /// </summary>
    /// <see cref="RuleExpressionBuilder"/>
    /// <example>
    ///  <code>
    ///     FactExpressionBuilder builder = new FactExpressionBuilder();
    ///     string[] expressions = builder.Createbuilder.CreateStringCriteria("COUNTRY").IsEqualTo("US")
    ///            .AndNumericCriteria("POLICY_YEAR").IsEqualTo("2011").CriteriaExpression;
    ///     //Once a call to CriteriaExpression is called the buffer is cleared for new expression building
    ///  </code>
    /// </example>
    public class ExpressionBuilder<T> where T : IExpressionPredicate, new()
    {  
        Queue<string> buffer;

        internal ExpressionBuilder()
        {
            buffer = new Queue<string>();
        }

        internal ExpressionBuilder(Queue<string> Buffer)
        {
            buffer = Buffer;
        }

        private T CreateCriteria(string CriteriaName, string DataType)
        {
            if (string.IsNullOrEmpty(CriteriaName))
                throw new ArgumentNullException("CriteriaName");

            buffer.Enqueue(CriteriaName);
            buffer.Enqueue(DataType);

            T criteriaPredicate = new T();
            criteriaPredicate.Buffer = this.buffer;
            
            return (T)criteriaPredicate;
        }

        public T CreateStringCriteria(string CriteriaName)
        {
            return CreateCriteria(CriteriaName, "STRING");
        }

        public T CreateDateCriteria(string CriteriaName)
        {
            return CreateCriteria(CriteriaName, "DATE");
        }

        public T CreateBooleanCriteria(string CriteriaName)
        {
            return CreateCriteria(CriteriaName, "BOOLEAN");
        }

        public T CreateNumericCriteria(string CriteriaName)
        {
            return CreateCriteria(CriteriaName, "NUMERIC");
        }
    }
}
